using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows.Forms;
using OhioState.AssetManaged;

namespace OhioState.Controls.AssetMgr
{
    //
    // AssetManagerControl - This is a generic DataGridView control
    //  designed to view, select, preview, and rename the contents of the asset
    //  manager.  It can be initialized to view objects of a certain type or
    //  simply all of the objects in the asset manager.
    //
    public partial class AssetManagerDropDownControl : UserControl
    {
        //
        // Desired Type - "" = everything
        //
        Type type;

        //
        // Event for changing selection and notifying about items being updated
        //
        public event IAssetManagedHandler SelectedEvent;
        //public event IAssetManagedHandler UpdatedEvent;

        //
        // Asset Manager events
        //
        //private IAssetManagedHandler assetManAddItemEvent;
        //private IAssetManagedHandler assetManRemoveItemEvent;
        //private Dictionary<IAssetManaged, IAssetManagedHandler> updateEvents;

        //
        // Event helper for firing events
        //
        protected OhioState.AssetManaged.EventsStrategyAbstract _eventsHelper;

        //
        // Constructor
        //
        public AssetManagerDropDownControl()
        {
            InitializeComponent();

            //_eventsHelper = new EventsStrategyOneWay();
            _eventsHelper = new EventsStrategySerial();
        }

        //
        // Init function sets the type that this control will be watching for.
        //  It also gets a pointer to the asset manager, which enables the control
        //  to work.  If this function has not been called, the control will not
        //  perform any tasks.
        //  This function also populates the data grid view off of what is currently in 
        //   the asset manager at creation time.
        //  If desired_type is the null then this control will create a
        //   view of all types of objects.
        //
        public void Init(Type desired_type)
        {
            //
            // Set up event handlers for add and remove items
            //
            AssetManager.Instance.AssetAdded += new IAssetManagedHandler(updateList);
            AssetManager.Instance.AssetRemoved += new IAssetManagedHandler(updateList);

            // Set type
            type = desired_type;

            // Ensure the data grid is clear of anything that may have been in it before
            comboBox.Items.Clear();

            //
            // Populate data grid view
            //
            PopulateComboBox();
            //List<IAssetManaged> list = AssetManager.Instance.GetItems(type);
            //foreach (IAssetManaged asset in list)
            //{
            //    assetManagerDropDown_AddItemEvent_thisThread(asset);
            //}
        }

        //
        // Select the row of the combo box that this object is in.
        //
        public void SelectItem(IAssetManaged asset)
        {
            ClearSelection();
            if (asset != null)
            {
                comboBox.SelectedItem = asset;
            }
        }

        //
        // Deselect every item
        //
        private void ClearSelection()
        {
            comboBox.SelectedItem = null;
        }

        //
        // Returns the currently selected item or null if there is none.
        //
        public IAssetManaged GetSelected()
        {
            return (IAssetManaged)comboBox.SelectedItem;
        }

        //
        // Event handler that gets triggered when an object is added to the asset manager.
        //  This function first checks if it is the correct type of object before adding
        //  it to the combo box.  
        //
        public void updateList(IAssetManaged asset)
        {
            IAssetManaged selection = GetSelected();
            PopulateComboBox();
            SelectItem(selection);
        }

        //public static bool MyInterfaceFilter(Type typeObj, Object criteriaObj)
        //{
        //    if (typeObj.ToString() == criteriaObj.ToString())
        //        return true;
        //    else
        //        return false;
        //}
        //
        // Force the event to get called on the proper thread.  The ComboBox complains if you try
        //  to use it on the wrong thread.
        //
        //public void assetManagerDropDown_AddItemEvent(IAssetManaged asset)
        //{
        //    IAssetManagedHandler newEvent = new IAssetManagedHandler(assetManagerDropDown_AddItemEvent_thisThread);
        //    object[] args = new object[1];
        //    args[0] = asset;
        //    //
        //    // We need to make sure these methods are executed on the correct thread.
        //    //
        //    try
        //    {
        //        if (this.InvokeRequired)
        //            this.Invoke(newEvent, args);
        //        else
        //            newEvent(asset);
        //    }
        //    catch { }
        //}

        //
        // Removes item from combo box when the remove event is received from the
        //  asset manager.  Update events are also removed.
        //
        //public void assetManagerDropDown_RemoveItemEvent_thisThread(IAssetManaged asset)
        //{
        //    foreach (Object item in comboBox.Items)
        //    {
        //        if (item == asset)
        //        {
        //            comboBox.Items.Remove(asset);
        //            //
        //            // Remove events
        //            //
        //            asset.RemoveChangedEventHandler(updateEvents[asset]);
        //            updateEvents.Remove(asset);

        //            _eventsHelper.Fire(UpdatedEvent, asset);
        //            break;
        //        }
        //    }
        //}
        //
        // Force the event to get called on the proper thread.  The ComboBox complains if you try
        //  to use it on the wrong thread.
        //
        //public void assetManagerDropDown_RemoveItemEvent(IAssetManaged asset)
        //{
        //    IAssetManagedHandler newEvent = new IAssetManagedHandler(assetManagerDropDown_RemoveItemEvent_thisThread);
        //    object[] args = new object[1];
        //    args[0] = asset;
        //    //
        //    // We need to make sure these methods are executed on the correct thread.
        //    //
        //    try
        //    {
        //        if (this.InvokeRequired)
        //            this.Invoke(newEvent, args);
        //        else
        //            newEvent(asset);
        //    }
        //    catch { }
        //}




        //
        // Select an item from combo box 
        //
        public void assetManagerDropDown_SelectItemEvent_thisThread(IAssetManaged asset)
        {
            comboBox.SelectedItem = asset;
        }
        //
        // Force the event to get called on the proper thread.  The ComboBox complains if you try
        //  to use it on the wrong thread.
        //
        public void assetManagerDropDown_SelectItemEvent(IAssetManaged asset)
        {
            IAssetManagedHandler newEvent = new IAssetManagedHandler(assetManagerDropDown_SelectItemEvent_thisThread);
            object[] args = new object[1];
            args[0] = asset;
            //
            // We need to make sure these methods are executed on the correct thread.
            //
            try
            {
                if (this.InvokeRequired)
                    this.Invoke(newEvent, args);
                else
                    newEvent(asset);
            }
            catch { }
        }


        //
        // Update event that gets called when an object is changed. Its only purpose here is to update the name.
        //
        //public void iAssetManaged_UpdateChangedEvent_thisThread(IAssetManaged asset)
        //{
        //    if (comboBox.Items.Contains(asset))
        //    {
        //        //
        //        // Remove and re-add the item to update its name
        //        //
        //        Object selected = comboBox.SelectedItem;
        //        comboBox.Items.Remove(asset);
        //        comboBox.Items.Add(asset);
        //        comboBox.SelectedItem = selected;
        //        _eventsHelper.Fire(UpdatedEvent, asset);
        //    }
        //}
        ////
        //// Force the event to get called on the proper thread.  The DataGridView complains if you try
        ////  to use it on the wrong thread.
        ////
        //public void iAssetManaged_UpdateChangedEvent(IAssetManaged asset)
        //{
        //    IAssetManagedHandler newEvent = new IAssetManagedHandler(iAssetManaged_UpdateChangedEvent_thisThread);
        //    object[] args = new object[1];
        //    args[0] = asset;
        //    //
        //    // We need to make sure these methods are executed on the correct thread.
        //    //
        //    try
        //    {
        //        if (this.InvokeRequired)
        //            this.Invoke(newEvent, args);
        //        else
        //            newEvent(asset);
        //    }
        //    catch { }
        //}

        //
        // Selection changed event which gets fired when the selection of the combo box changes.
        //  This in turn fires another event updating controls that might want to know that the selection
        //  has changed.
        //
        private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            _eventsHelper.Fire(SelectedEvent, GetSelected());
        }

        private void comboBox_DropDown(object sender, EventArgs e)
        {
            IAssetManaged asset = GetSelected();
            PopulateComboBox();
            comboBox.SelectedItem = asset;
        }

        private void PopulateComboBox()
        {
            List<IAssetManaged> assets = AssetManager.Instance.FindAll(type);
            comboBox.DataSource = assets;
        }
    }
}